
package dtu.app.activity;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.YuvImage;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;

import com.iqengines.demo.R;
import com.iqengines.sdk.IQE;
import com.iqengines.sdk.IQE.OnResultCallback;

import dtu.app.db.ProductDatabaseHelper;
import dtu.app.model.Product;

public class ScanActivity extends Activity {

	static final String KEY = "f266576ae21248229dd7197ca3b25787";
	static final String SECRET = "87e3c60615784cf0bd2ce47d9ad6dbbf";

	// Activates the local search.
	static final boolean SEARCH_OBJECT_LOCAL = true;

	// Activates the barcode scanning
	static boolean SEARCH_OBJECT_BARCODE = true;

	// Activates the scan search.
	static boolean SEARCH_OBJECT_SCAN = true;

	// Activates the snap search
	static boolean SEARCH_OBJECT_SNAP = true;

	// Activates the remote search.
	static final boolean SEARCH_OBJECT_REMOTE = true;

	// Maximum duration of a remote search.
	static final long REMOTE_MATCH_MAX_DURATION = 10000;

	//	static final int MAX_ITEM_HISTORY = 20;
	static final boolean PROCESS_ASYNC = true;
	static final boolean DEBUG = true;
	static IQE iqe;

	private static final String TAG = ScanActivity.class.getSimpleName();
	private Preview preview;
	private AtomicBoolean activityRunning = new AtomicBoolean(false);
	private Preview.FrameReceiver mreceiver;
	
	private JSONParser jsonParser;
	private ProductDatabaseHelper database;
	private AlertDialog alertDialog;
	private LayoutInflater inflater;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (DEBUG) Log.d(TAG, "onCreate");
		ActionBar actionBar = getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(true);
		actionBar.setHomeButtonEnabled(true);
		setContentView(R.layout.main);
		setTitle("Scan Groceries");
		initUI();
		initIqSdk();
		mreceiver = new CameraFrameReceiver();
		preview.mPreviewThread = preview.new PreviewThread("Preview Thread");
		preview.mPreviewThread.start();
	}

	private void initIqSdk() {
		iqe = new IQE(this, SEARCH_OBJECT_REMOTE,SEARCH_OBJECT_LOCAL, SEARCH_OBJECT_BARCODE, onResultCallback, KEY, SECRET);
	}

	@Override
	public void onDestroy() {
		iqe.destroy();
		super.onDestroy();
	}

	private void initUI() {
		preview = (Preview) findViewById(R.id.preview);		
	}

	@Override
	public void onResume() {
		super.onResume();
		activityRunning.set(true);
		iqe.resume();
		preview.setFrameReceiver(mreceiver);
		if(preview.mCamera!=null){
			unfreezePreview();
		}
	}

	@Override
	public void onPause() {
		if (DEBUG) Log.d(TAG, "onPause");
		stopScanning();
		iqe.pause();
		preview.stopPreview();
		activityRunning.set(false);
		super.onPause();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.scan_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}
	
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
	        case android.R.id.home:
	            finish();
	            return true;
	        case R.id.menu_temp_products:
	    		Intent intent = new Intent(this, TempProductActivity.class);
	            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
	            startActivity(intent);
	        	return true;
	        default:
	            return super.onOptionsItemSelected(item);
		}
	}

	private void startScanning() {
		if(SEARCH_OBJECT_SCAN){
			if(DEBUG) Log.d(TAG,"start scanning");
			preview.mPreviewThreadRun.set(true);
			iqe.goScan();
			preview.scan();
		}
	}

	private void stopScanning(){
		if(DEBUG) Log.d(TAG,"stop scanning");
		preview.mPreviewThreadRun.set(false);
	}

	private void unfreezePreview() {
		preview.startPreview();
		if(SEARCH_OBJECT_SCAN){
			startScanning();
		}
	}

	// Method that starts a local research on the phone. onResultCallback is called when result is ready.
	private void processImageScan(final YuvImage yuv) {
		if (DEBUG) Log.d(TAG,"scan decode message");
		iqe.goScan();
		Message.obtain(iqe, IQE.CMD_DECODE, IQE.scan, 0, yuv).sendToTarget();
	}
	
	public String qId, oId, oName, oMeta, json;
	
	// Interface used to communicate with the IQE class
	private OnResultCallback onResultCallback = new OnResultCallback() {

		@Override
		public void onQueryIdAssigned(String queryId, String pathName, int callType) {
			// TODO Auto-generated method stub
			// Not necessary to do anything /Jeppe
		}

		@Override
		public void onResult(String queryId, String objId, String objName, String objMeta, int engine, final int callType) {
			qId = queryId; oId = objId; oName = objName; oMeta = objMeta;
			
			json = objMeta.substring(objMeta.indexOf("\"")+1, objMeta.lastIndexOf("\""));
			
			if (null == inflater) inflater = getLayoutInflater();
			
			alertDialog = new AlertDialog.Builder(ScanActivity.this).create();
			alertDialog.setTitle("Result");
			View dialogView = inflater.inflate(R.layout.scanned_dialog, null);
			InputStream is = null;
			try {
				is = getApplicationContext().getAssets().open("iqedata/" + objId + "/" + objId + ".jpg");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
			Bitmap origBmp = BitmapFactory.decodeStream(is);
			((TextView)dialogView.findViewById(R.id.scanned_item_description)).setText("Scanned item: " + objName);
			((ImageView)dialogView.findViewById(R.id.scanned_item_image)).setImageBitmap(origBmp);
			alertDialog.setView(dialogView);
			
			alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
				@Override
                public void onClick(DialogInterface dialog, int which) {
                	Product product = new Product();
        			try {
        				jsonParser = new JSONParser();
        				Object obj = jsonParser.parse(json);
        				JSONObject jsonObject = (JSONObject) obj;
        				
        				product.setName(oName);
        				product.setCategory((String) jsonObject.get("category"));
        				product.setUnit((String) jsonObject.get("unit"));
        				product.setPieces((Long) jsonObject.get("pieces"));
        				product.setPiecesAmount((Double) jsonObject.get("pieces_amount"));
        				product.setTotalAmount((Double) jsonObject.get("total_amount"));
        				product.setImagePath("iqedata/" + oId + "/" + oId + ".jpg");
        				database = new ProductDatabaseHelper(getBaseContext());
        				database.insertProduct(product, true); // true for insert in tempList

        			} catch (ParseException e) {
        				Log.e("ScanActivity", "JSON parse error: " + e.getMessage());
        			}
        			startScanning();
                }
            });
			
			alertDialog.setButton2("Cancel", new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					startScanning();
				}
			});
			
			alertDialog.setOnCancelListener(new OnCancelListener() {
				@Override
				public void onCancel(DialogInterface dialog) {
					startScanning();
				}
			});
			
			alertDialog.show();
		}

		@Override
		public void onNoResult(int callType, Exception e, File imgFile) {
			startScanning();
		}
	};

	class CameraFrameReceiver implements Preview.FrameReceiver {

		@Override
		public void onFrameReceived(byte[] frameBuffer, Size framePreviewSize) {

			if (!preview.mPreviewThreadRun.get()) {
				return;
			}

			if(frameBuffer == null){
				if (DEBUG) Log.d(TAG,"no picture");
				return;
			}

			YuvImage yuvImage = new YuvImage(frameBuffer, 17, framePreviewSize.width, framePreviewSize.height, null);
			// analyze the picture.
			processImageScan(yuvImage);
		}
	}

}
